package com.devicemantra.coordinate.dataobjects;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.jdo.JDOException;
import javax.jdo.JDOHelper;
import javax.jdo.JDOObjectNotFoundException;
import javax.jdo.JDOUserException;
import javax.jdo.ObjectState;
import javax.jdo.PersistenceManager;

import com.devicemantra.coordinate.ds.tests.PMF;
import com.devicemantra.coordinate.exceptions.dataobjects.CDatabaseException;
import com.devicemantra.coordinate.exceptions.operations.CDepartmentAlreadyExistsException;
import com.devicemantra.coordinate.exceptions.operations.CDepartmentDoesNotExistsException;
import com.devicemantra.coordinate.exceptions.operations.CException;
import com.google.appengine.api.datastore.Blob;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.Query;

/** TODO - Most of the *Factory classes are written very badly 
 * put some thought into optimizing for performance */
public class CDepartmentFactory 
{
		public static boolean checkDepartmentExists(String pDepartmentName)
		{
			boolean lDoesExist = true;
			Key lNewDepartmentKey = KeyFactory.createKey(CDepartment.class.getSimpleName(), pDepartmentName);
			PersistenceManager pm = PMF.get().getPersistenceManager();
			try
			{
				pm.getObjectById(CDepartment.class,lNewDepartmentKey);
			} catch(JDOObjectNotFoundException e)
			{
				lDoesExist = false;
			}
			pm.close();
			return lDoesExist;
		}
		
		private static Key createKey(String pDepartmentName)
		{
			Key lNewDepartmentKey = KeyFactory.createKey(CDepartment.class.getSimpleName(), pDepartmentName);
			return lNewDepartmentKey;
		}
		
		private static CDepartment getDepartmentByKey(String pDepartmentKey)
		{
			CDepartment lDept = null;
			PersistenceManager pm = PMF.get().getPersistenceManager();
			try
			{
					lDept = pm.getObjectById(CDepartment.class,pDepartmentKey);
					pm.retrieve(lDept);
					lDept = pm.detachCopy(lDept);
					if( lDept.getSubDepartments() == null)
					{
					//	System.out.println("Sub department list was NULL");
					}
					else
					{
					//	System.out.println("Sub department list was NOT NULL");
					//	System.out.println("Number of sub departments " + lDept.getSubDepartments().size());
						
					}
			} catch(JDOObjectNotFoundException e)
			{
					System.out.println("[COORDINATE] ERROR: Some problem retreiving object");
					e.printStackTrace();
			}
			
			pm.close();
			return lDept;
		}
		
		public static CDepartment getDepartment(String pDepartmentName) throws CDepartmentDoesNotExistsException
		{
			CDepartment lDept = null;
			if( checkDepartmentExists(pDepartmentName))
			{
				Key lDepartmentKey = createKey(pDepartmentName);
				try
				{
					PersistenceManager pm = PMF.get().getPersistenceManager();
					/* Let us add a fetch depth so that root and sub objects are retrieved */
					pm.getFetchPlan().setMaxFetchDepth(2);
					lDept = pm.getObjectById(CDepartment.class,lDepartmentKey);
					lDept = pm.detachCopy(lDept);
					pm.close();
				} catch(JDOObjectNotFoundException e) {
					System.out.println("[COORDINATE] ERROR: Some problem retreiving object");
					e.printStackTrace();
					lDept = null;
				}
			}else {
				throw new CDepartmentDoesNotExistsException("ERROR: Department does not exist : Name :" + pDepartmentName);
			}
			return lDept;
		}
		
		
		
		
		public static List<CDepartment>  getAllDepartments()
		{
			List<CDepartment> lListDepts = null;
			try {
			PersistenceManager pm = PMF.get().getPersistenceManager();
			javax.jdo.Query query = pm.newQuery(CDepartment.class);
			/*query.setFilter("mDepartmentName == lDeptName");
			query.declareParameters("String lDeptName");*/
		    lListDepts = (List<CDepartment>) query.execute(/*"FINANCE" */);
		    /*
		    Iterator<Department> lListDeptsIter = lListDepts.iterator();
		    while (lListDeptsIter.hasNext())
		    {
	               Department lDept = lListDeptsIter.next();
					System.out.println("DEPARTMENT NAME - " + lDept.getDepartmentName());
					List<SubDepartment> lSubDeptList = lDept.getSubDepartments();
					if( lSubDeptList == null )
					{
						System.out.println("List was null :(");
					}
					else
					{
						System.out.println("List was NOT null ");
					}
	        }
	        */
		    pm.detachCopyAll(lListDepts);
		    //List<Department> lNewListDepts = (List<Department>) pm.detachCopyAll(lListDepts);
		    pm.close();
		    for( int counter = 0; counter < lListDepts.size(); counter++)
		    {
		    	CDepartment lDept = lListDepts.get(counter);
		    	//System.out.println("Department name is " + lDept.getDepartmentName());
		    	//System.out.println("Department Sub dept size is " + lDept.getSubDepartments().size());
		    }
		    
			} catch(JDOException e ) {
				e.printStackTrace();
			}
			
			return lListDepts;
		}
	
		public static CDepartment createNewDepartment(String pNewDepartmentName) throws CDepartmentAlreadyExistsException
		{
			/* First check whether such a Department exists using Keys */
			boolean lDoesDeptExist = checkDepartmentExists(pNewDepartmentName);
			if(false == lDoesDeptExist)
			{
				CDepartment lDepartment = new CDepartment(pNewDepartmentName);
				Key lNewDepartmentKey = createKey(pNewDepartmentName);
				System.out.println("Department Key is " + KeyFactory.keyToString((lNewDepartmentKey)));
				lDepartment.setDepartmentId(lNewDepartmentKey);
				return lDepartment;
			}
			throw new CDepartmentAlreadyExistsException();
			/* Department with that name already exists */
		}
		
		public static void createNewDepartment(	String pNewDepartmentName,
														String pDeptDesc,
														Logo pLogo,
														ContactInfo pContactInfo) throws CDepartmentAlreadyExistsException
		{
			/* First check whether such a Department exists using Keys */
			boolean lDoesDeptExist = checkDepartmentExists(pNewDepartmentName);
			if(false == lDoesDeptExist)
			{
				CDepartment lDepartment = new CDepartment(pNewDepartmentName,pDeptDesc,pLogo,pContactInfo);
				Key lNewDepartmentKey = createKey(pNewDepartmentName);
				System.out.println("Department Key is " + KeyFactory.keyToString((lNewDepartmentKey)));
				lDepartment.setDepartmentId(lNewDepartmentKey);
				PersistenceManager pm = PMF.get().getPersistenceManager();
				pm.makePersistent(lDepartment);
				pm.close();
				
			}else
			{
				/* Department with that name already exists */
				throw new CDepartmentAlreadyExistsException();
			}
			
		}
		
		
		public static void  deleteDepartment(String pDepartmentName) throws CDepartmentDoesNotExistsException, CDatabaseException
		{
			/* First check whether such a Department exists using Keys */
			boolean lIsDeleteSuccess = false;
			boolean lDoesExist = checkDepartmentExists(pDepartmentName);
			
			if(false == lDoesExist)
				throw new CDepartmentDoesNotExistsException("ERROR: Department does not exist");
			
			Key lDeptKey = createKey(pDepartmentName);
			CDepartment lDept = null;
			try
			{
				PersistenceManager pm = PMF.get().getPersistenceManager();
				lDept = pm.getObjectById(CDepartment.class,lDeptKey);
				pm.deletePersistent(lDept);
							
			} catch(JDOObjectNotFoundException e)
			{
				System.out.println("[COORDINATE] ERROR: Some problem retreiving object");
				e.printStackTrace();
				throw new CDatabaseException("ERROR: Could not find the Department object now !!");
			}
			
		}
		
		public static void persistDepartment(CDepartment pDepartment) throws CException 
		{
			/*ObjectState state = JDOHelper.getObjectState(pDepartment);
			System.out.println("Object WAS in " + state.name());
			pDepartment.setDescription("New location near NMC");
			state = JDOHelper.getObjectState(pDepartment);
			System.out.println("Object IS now in " + state.name()); */
			PersistenceManager pm = PMF.get().getPersistenceManager();
			try {
				pm.makePersistent(pDepartment);
			}catch(JDOUserException e) {
				throw new CException(e.getMessage());
			}finally {
			pm.close();
			}
			
		}
		
		
}
